文件操作
文件操作
open - 重要
我们首先需要创建一个文件对象,借由这个对象实现对文件的读写。
open() 方法用于打开一个文件,并返回文件对象。在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
参数说明:
-
file: 必需,文件路径(相对或者绝对路径)。
- 相对路径的起点为 open 方法所在 py 文件的文件夹
-
mode: 可选,文件打开模式,后面详细解答
-
buffering: 设置缓冲,用于读和写。
buffering 是一个可选整数,用于设置缓冲策略。
-
0:来关闭缓冲 (仅在二进制模式下允许),这种状况下,write() 方法不能直接传入字符串类型的变量,而是传入字符串编码后的字节类型的变量
-
1:来选择行缓冲 (仅在文本模式下可用),只缓冲一行,最终的效果就是,(首先所有的数据都会先写入缓冲区)一旦缓冲区中的字符出现一个换行,缓冲区中的数据刷入文件中。所以当我们使用 write() 方法写入文件的时候,只要写入的内容中包含换行符
\n
,就相当于在 write() 方法后调用了一次 flush() 方法 -
传递一个 > 1 的整数(单位为字节),这个整数表示固定大小的块缓冲区的大小。(仅在二进制模式下能生效,文本模式下不生效,虽然官方文档没说,但是我测试出来是这样的)
使用文本模式的时候,指定 open 的 buffering 参数为一个>1 的值,但是并不生效,关于这个问题的讨论:
python - buffering argument of open() seemingly ignored when working with text I/O - Stack Overflow -
不传此参数(默认值为 None),默认的缓冲策略如下
-
如果被读文件是二进制文件,则被缓冲在固定大小的缓冲区中; 缓冲区的大小是通过尝试确定底层设备的“块大小(block size)”即参数
io.DEFAULT_BUFFER_SIZE
。在许多系统上,缓冲区通常是 4096 或 8192 字节长。我的系统是 Win11,缓存大小是 8192# 8192 import io print (io.DEFAULT_BUFFER_SIZE)
-
如果是交互式的文本文件(isatty() 返回 True 的文件),则使用行缓冲,使用行缓冲。其他非交互式的文本文件跟二进制文件使用的策略一样。
-
-
-
encoding: 一般使用 utf-8,只能在文本模式下设置此参数
关于文件编码相关的知识和操作,请看《基本语法.md》的
字符串的编码
小节 -
errors: 报错级别,注意在二进制模式下无法使用此参数
- 'strict' 用于在编码错误时引发 ValueError 异常 (默认值 None 具有相同的效果)
- 'ignore',忽略编码错误。(注意,忽略编码错误可能导致数据丢失。)
-
newline: 设置换行符,仅在文本模式下有效
-
closefd: 如果 closefd 为 False,则在关闭文件时,底层文件描述符将保持打开状态。这在给定文件名时不起作用,在这种情况下必须为 True。(没懂)
常用参数就三个:
-
file
-
mode
-
encoding
buffering 有时候也会手动设置一下
现在重点说一下 mode 参数,
模式的值,只能 create
(对应 x
)、read
(对应 r
)、write
(对应 w
)、append
(对应 a
)中的一种,然后再搭配 b
(二进制模式)、+
(增加读或者写功能),不能随意组合出 rw
这种模式。
默认为 rt,也就是读文本模式。
模式 | 描述 |
---|---|
t | 文本模式 (默认)。 |
x | 写模式,新建一个文件,如果该文件已存在则会报错。 |
b | 二进制模式。 |
+ | 打开一个文件进行更新 (可读可写)。 |
U | 通用换行模式(Python 3 不支持)。 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。如果文件不存在则会报错。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。可用于边读边改的场景 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
简单总结,横向对比如下:
模式 | r | r+ | w | w+ | a | a+ |
---|---|---|---|---|---|---|
读 | + | + | + | + | ||
写 | + | + | + | + | + | |
创建 | + | + | + | + | ||
覆盖 | + | + | ||||
指针在开始 | + | + | + | + | ||
指针在结尾 | + | + |
返回结果:
Open() 返回一个文件对象,其类型取决于 mode 参数,并且通过这些类型的文件对象来实现标准文件操作,比如的读写。
-
当使用 open() 以文本模式 ('w','r','wt','rt' 等) 打开文件时,它返回一个 TextIOWrapper。
-
当以二进制模式打开文件时,返回的类型有多种请看
-
二进制读(rb),返回 BufferedReader
-
在二进制写(wb)和二进制追加(ab),返回 BufferedWriter
-
在读/写模式 (r+,w+,a+) 下,返回 BufferedRandom。
-
close
注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。
我们用 Python 的 open 方法打开一个文件之后,会占用这个文件,此时,其他的工具无法删除这个文件,也无法重命名这个文件,(但是是可以看到和更新这个文件的),因此,我们使用完一个文件之后,一定要记得 close。解除占用。
在 Windows 上,创建了文件对象之后,读取文件内容之前,通过别的工具修改文件的内容,python 的文件对象是可以看到这个更新的内容的
同时,close() 方法在调用的时候,也会把保留在缓存中的内容写入到文件中。然后再关闭文件对象
一个好的习惯是,创建了文件对象之后,立即写一个关闭方法,这样,就不容易忘掉调用关闭方法
读操作
open 方法的 mode 选择以 r 开头的即可
文件指针
我们在读取文件的时候,有一个文件指针标识我们当前在哪里,所有的读取操作都是以指针所在位置为相对位置进行操作,读操作会默认向后移动这个文件指针,多次调用读操作的时候,后面的读操作使用的是前面的读操作移动之后的文件指针。
我们可以通过 tell 方法知道当前指针所处的位置,以及可以通过 seek 方法随意修改指针的位置,实现从任意位置开始读文件。
文件指针默认指向文件的第一个字符(文本模式)或者字节(二进制模式)。
常用方法
读文件:
-
read,用于从文件中当前指针所在位置开始读取指定的字符数(文本模式 t)或字节数(二进制模式 b),如果未给定参数 size 或 size 为负数则读取文件所有内容到一个字符串中。size 默认为 -1。
读取到文件末尾,则会返回空字节
b''
,并且一直调用,会一直返回空字节 -
readline,用于从文件当前指针所在位置开始读取整行,包括 换行符(可以用字符串的 strip 方法去除)。如果指定了一个非负数的参数,则返回指定大小的字节数,其中换行符也算字节数。
已经读取了最后一行之后,再调用此方法,会返回空字符串,并且一直调用,会一直返回空字符串
如果模式带 b,读取的就是一行内容的字节(但是数字字符和英文字符还是原来的样子,在 utf-8 或者 unicode 编码中,字母和数字兼容 ASCII 编码,所以没有编码,编码就是自身),想要展示为字符串,需要解码
-
readlines,从当前指针所在位置开始,将后面的所有的数据都读取到一个列表中,每一个元素表示文件中的一行内容,如果是文本模式,这一行内容就是文本,如果是二进制模式,这一行内容就是二进制文本对应的字节数据
其实读文件问了避免频繁访问系统磁盘,也是有缓冲的,对缓冲区的配置,请看 open
小节的 buffering 参数
读缓冲演示起来不直观,这里我们就不写代码演示了
查看和移动文件当前的指针所在的位置:
-
tell:返回文件的当前位置,即文件指针当前位置, 它是从文件开头开始算起的字节数。
常见字符的字节数
-
一个数字字符算 1 个字节,
-
一个字母字符算 1 个字节,
-
一个换行符算两个字节,在 Windows(
\r\n
)中占两个字节,在 Linux(\n
)中占一个字节在不同的操作系统和文件格式中,换行符可能会有所不同。常见的换行符有:
- Windows 中的换行符为 "\r\n",占用两个字节。
- Linux 和 macOS 中的换行符为 "\n",占用一个字节。
- Macintosh 中的换行符为 "\r",占用一个字节。
-
一个中文字符算 3 个字节
这个跟 Java 不一样,Java 中一个中文字符占用 2 个字节
-
-
seek:用于移动文件读取指针到指定位置。
f.seek(offset, from_what) 函数。
-
offset 需要移动偏移的字节数,表示字符个数,正数表示向后移动,负数表示向前移动,在正常情况下,我们应该是在二进制模式下使用 seek 方法,在非二进制模式下(比如文本模式),可以使用 seek() 方法,但是 offset 参数必须是 0
-
from_what 表示相对位置, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,
例如:
-
seek(x,0) :从起始位置即文件首行首字符开始向后移动 x 个字节
-
seek(x,1) :表示从当前位置往后移动 x 个字节
-
seek(-x,2):表示从文件的结尾往前移动 x 个字节
-
实践
遍历结果
我们可以先 readlines 读出所有的行,然后 for 循环遍历这个列表,也可以直接 for 循环遍历文件对象
# 文件可以为绝对路径,也可以为相对路径
# file_path = "C:/Users/wwwli/Desktop/test_file.txt"
# 相对路径的起点即当前py文件所在的目录
# mode为 r 或者r+ 的时候,路径对应的文件必须存在,否则报错
# mode为 w w+ a a+ 的时候,路径对应的文件可以不存在,不存在的时候会自动创建
file_path = "./test_file.txt"
# 因为我们在编写文件的时候,使用的就是UTF-8编码,所以我们读取的时候,也要指定编码为 UTF-8
# 读取文件内容
file_test = open(file_path, mode="r", encoding="UTF-8")
# <class '_io.TextIOWrapper'>
print(type(file_test))
# 从当前指针所在位置开始,将后面的所有的数据都读取到一个列表中
# 每一个元素表示文件中的一行内容
content_list = file_test.readlines()
# print(content_list)
# for 循环遍历
for line in content_list:
print(line, end="")
print()
# close() 方法用于关闭一个已打开的文件。关闭后的文件不能再进行读写操作, 否则会触发 ValueError 错误。 close() 方法允许调用多次。
# 当 file 对象,被引用到操作另外一个文件时,Python 会自动关闭之前的 file 对象。 使用 close() 方法关闭文件是一个好的习惯。
# close在最终关闭文件对象之前,会自动调用flush方法
# 文件对象最后需要关闭
file_test.close()
print("-----------")
# 其实可以直接将文件对象拿来循环,感觉是自动调用了文件对象的readlines方法
# 但是这有一个问题啊,怎么关闭文件对象呢?
# 此时 文件对象未关闭
for line in open(file_path, mode="r", encoding="UTF-8"):
print(line, end="")
print()
print("-----------")
输出:
<class '_io.TextIOWrapper'>
11111111111
22222222222222
33333333333
AAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCC
卧槽,真牛逼,真的假的
-----------
11111111111
22222222222222
33333333333
AAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCC
卧槽,真牛逼,真的假的
-----------
通过 with open 语法,可以自动帮我们关闭文件对象,防止我们忘记
关于 with 关键字,请看《错误和异常处理.md》中的
预定义的finally
小节
# with open 语法,可以自动帮我们关闭文件对象,防止我们忘记
with open(file_path, mode="r", encoding="UTF-8") as file_handler:
content = file_handler.read()
print(content, type(content))
print("-----------")
输出:
11111111111
22222222222222
33333333333
AAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCC
卧槽,真牛逼,真的假的 <class 'str'>
-----------
如果文件比较大,我们可以使用生成器读取文件内容,这样,就不用将文件中的所有内容读到内存中,占用内存
def file_iterator(file_obj):
while True:
# readline() 方法用于从文件当前指针所在位置开始读取整行,包括 换行符(可以用字符串的strip方法去除)。如果指定了一个非负数的参数,则返回指定大小的字节数,其中换行符也算字节数
# 已经读取了最后一行之后,在调用此方法,会返回空字符串,并且一直调用,一直返回空字符串
line_str = file_obj.readline()
# 空字符串 '' ,作为条件表达式,会被bool()转化为 Boolean,结果为 False
if line_str:
yield line_str
else:
# 抛出 StopIteration
return
file_obj = open(file_path, mode="r", encoding="UTF-8")
line_reader = file_iterator(file_obj)
print(next(line_reader))
print(next(line_reader))
for line in line_reader:
print(line, end="")
print()
file_obj.close()
print("--------------------------------")
输出:
11111111111
22222222222222
33333333333
AAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCC
卧槽,真牛逼,真的假的
--------------------------------
查看文件当前的指针所在的位置
# 查看文件读取到哪里了
# 读写文件的时候,有一个指针标识我们当前在哪里,所有的读写操作都是从当前位置开始的
# tell() 方法返回文件的当前位置,即文件指针当前位置, 它是从文件开头开始算起的字节数。
# 常见字符的字节数
# 一个数字字符算1个字节,
# 一个字母字符算1个字节,
# 一个换行符算两个字节,在Windows中占两个字节,在Linux中占一个字节
# 一个中文字符算3个字节,这个跟Java不一样,Java中一个中文字符占用2个字节
#
# 文件内容为 Python真棒
file_path_char = "./char_test.txt"
char_file = open(file_path_char, mode="r", encoding="UTF-8")
print(char_file.readline())
# 整个文件就一行, 调用一次 readline就读完了, 所以当前的位置可以算出来, 6*6 + 2*3 12个字节
print(char_file.tell())
# 在不带b的模式下,可以使用seek() 方法,但是 offset 参数必须是 0
# 回到开头,可以继续读第一行
char_file.seek(0, 0)
# read() 方法用于从文件中当前指针所在位置开始读取指定的字符数(文本模式 t)或字节数(二进制模式 b),如果未给定参数 size 或 size 为负数则读取文件所有内容到一个字符串中。size默认为 -1
# 输出从当前指针开始的6的字符,也就是输出 Python
print(char_file.read(6))
char_file.seek(0, 1)
print(char_file.readline())
char_file.seek(0, 2)
print(char_file.readline())
print("--------------------------------")
输出:
Python真棒
12
Python
真棒
--------------------------------
移动移动文件当前的指针所在的位置
通过移动文件指针的位置,我们可以从文件的任意位置读取任意个数的字节,但是要注意,(在使用二进制模式的时候)要将字节解码为中文的时候,很有可能因为会因为字节不完整,导致无法解码,比如真棒这两个字总共 6 个字节,结果字节对象里只有 5 个字节,那这样进行解码的时候就会报错
为了不报错,我们可以指定 errors 参数 decode(encoding='utf-8', errors='ignore')
,这样,当无法解码的时候,就不会报错。
本质上来说,从任意位置读取字节,然后将其转化为中文字符,这个操作还是比较有难度和风险的
# seek() 方法用于移动文件读取指针到指定位置。
# f.seek(offset, from_what) 函数。
# offset 需要移动偏移的字节数,表示字符个数,正数表示向后移动,负数表示向前移动
# from_what 表示相对位置, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,
# 例如:
# seek(x,0) :从起始位置即文件首行首字符开始向后移动 x 个字节
# seek(x,1) :表示从当前位置往后移动x个字节
# seek(-x,2):表示从文件的结尾往前移动x个字节
#
# 文件内容为 Python真棒
file_path_binary_char = "./char_binary_test.txt"
char_file = open(file_path_binary_char, mode="rb")
# rb 模式下,readline方法读出来的是字节(但是数字字符和英文字符还是原来的样子,在utf-8或者unicode编码中,字母和数字兼容 ASCII 编码,所以没有编码,编码就是自身),想要展示为字符串,需要解码
# b'Python\xe7\x9c\x9f\xe6\xa3\x92'
print(char_file.readline())
# 输出 12
print(char_file.tell())
# 回到开头
char_file.seek(0, 0)
# 然后移动到倒数 2个中文字符,和3个英文字符,也就是9个字节
char_file.seek(-9, 2)
# 再向后移动3个英文字符,也就是3个字节
char_file.seek(3, 1)
# read() 方法用于从文件读取指定的字符数(文本模式 t)或字节数(二进制模式 b),如果未给定参数 size 或 size 为负数则读取文件所有内容。默认为 -1
# 输出从当前指针开始的6个字节,也就是两个中文字符,输出 真棒 对应的字节
binary_read = char_file.read(6)
# b'\xe7\x9c\x9f\xe6\xa3\x92' <class 'bytes'>
print(binary_read, type(binary_read))
# 输出 编码为中文:真棒
print("编码为中文:" + binary_read.decode('utf-8', ))
# 在使用带b的模式的时候,要将字节解码为中文的时候,很有可能因为会因为字节不完整,导致无法解码,比如真棒这两个字总共6个字节,结果字节对象里只有5个字节,那这样进行解码的时候就会报错
# 为了不报错,我们可以指定errors参数 decode(encoding='utf-8', errors='ignore'),这样,当无法解码的时候,就不会报错
print("--------------------------------")
输出:
b'Python\xe7\x9c\x9f\xe6\xa3\x92'
12
b'\xe7\x9c\x9f\xe6\xa3\x92' <class 'bytes'>
编码为中文:真棒
--------------------------------
边读边改
TODO
写操作
open 方法的 mode 选择以 w 或者 a 开头的即可
常用方法
-
write,用于向文件中写入指定字符串或者字节。在文件关闭前或缓冲区刷新前,写入的内容存储在缓冲区中,这时你在文件中是看不到写入的内容的。刷新之后才能在文件中看到内容
文件打开模式带 b 的时候,写入文件内容时,字符串要用 encode 方法转为 bytes 形式,否则报错:TypeError: a bytes-like object is required, not 'str'。
-
writelines,用于向文件中写入一序列的字符串。这一序列字符串可以是由迭代对象产生的,如一个字符串列表。注意,此方法不会自动添加换行,想要换行需要在列表元素(字符串)中手动添加换行符
\n
。 -
flush,用来刷新缓冲区,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,调用此方法可以手动刷新缓冲区,而不是被动的等待缓冲区满了之后或者调用 close 方法自动刷新缓冲区。一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。
-
truncate,用于截断文件并返回截断的字节长度。如果指定长度(字节数)的话,就从文件的开头开始截断指定长度,其余内容删除;不指定长度的话,就从文件开头开始截断到当前位置,其余内容删除。
-
isatty : isatty() 方法是 Python 中的内置方法,用于检查文件流在 Python 中是否是交互式的,即在终端中打开了文件,并且可以编辑。如果是,则它将是交互式的,并且该方法将返回“ True”。比如在 Linux 命令中用 vim 命令编辑文件。
# True import sys print(sys.stdout.isatty())
很奇怪的是,Python 并没有自动在内容后面加上换行的方法,可能是为了兼容二进制模式
我们调用 write 方法,内容并未真正直接写入文件,而是会积攒在程序的内存中,称之为缓冲区,当调用 flush 的时候,内容会真正写入文件,为什么这么做,这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)
实践
简单实践
这里我们演示写入,其实追加写也很简单,将模式改为以 a 开头即可
# mode为 r 或者r+ 的时候,路径对应的文件必须存在,否则报错
# mode为 w w+ a a+ 的时候,路径对应的文件可以不存在,不存在的时候会自动创建
file_path_write = "./write_test.txt"
file_write = open(file_path_write, mode="w", encoding="UTF-8")
for i in range(0, 10):
# write() 方法用于向文件中写入指定字符串。
# 在文件关闭前或缓冲区刷新前,字符串内容存储在缓冲区中,这时你在文件中是看不到写入的内容的。
# 如果文件打开模式带 b,那写入文件内容时,str (参数)要用 encode 方法转为 bytes 形式,否则报错:TypeError: a bytes-like object is required, not 'str'。
file_write.write(str(i) + "\n")
line_list = ["批量插入1\n", "批量插入2\n", "批量插入3\n", "批量插入4\n"]
# writelines() 方法用于向文件中写入一序列的字符串。
# 这一序列字符串可以是由迭代对象产生的,如一个字符串列表。
# 换行需要制定换行符 \n。
file_write.writelines(line_list)
# flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。
# 一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。
file_write.flush()
file_write.close()
写入的文件
0
1
2
3
4
5
6
7
8
9
批量插入1
批量插入2
批量插入3
批量插入4
缓冲区配置实践
对缓冲区的配置,请看
open
小节的 buffering 参数,
Python 的文件操作自带缓存,确守比 Java 方便
行缓冲
意思是,只缓冲一行,最终的效果就是,(首先所有的数据都会先写入缓冲区)一旦缓冲区中的字符出现一个换行,缓冲区中的数据刷入文件中。所以当我们使用 write() 方法写入文件的时候,只要写入的内容中包含换行符 \n
,就相当于在 write() 方法后调用了一次 flush() 方法
file_path_write_buffer = "./write_buffer_test.txt"
# buffering=1 行缓存
# 如果模式为a,则会一直追加
file_write_buffer = open(file_path_write_buffer, mode="a", encoding="UTF-8", buffering=1)
# 使用write()方法写入文件的时候,只要写入的内容中包含换行符`\n`,就相当于在write()方法后调用了一次flush()方法
file_write_buffer.write("1111")
file_write_buffer.write("222\n")
file_write_buffer.write("333")
file_write_buffer.write("444\n")
file_write_buffer.write("55555")
file_write_buffer.write("666\n777777")
file_write_buffer.write("88888")
file_write_buffer.flush()
file_write_buffer.close()
效果就是,
写完 222\n
,刷新缓冲区,文件中添加 1111222\n
写完 444\n
,刷新缓冲区,文件中添加一行 333444\n
以此类推,到写完 666\n777777
的时候,777777
也会被刷新到磁盘文件中。
指定大小的缓冲区
指定大小的缓冲区,仅在二进制模式下能生效,文本模式下不生效,很好用
file_path_write_buffer_2 = "./write_buffer_test_2.txt"
# buffering > 1 的缓存设置
# 仅在二进制模式下能生效,文本模式下不生效,虽然官方文档没说,但是我测试出来是这样的
file_write_buffer_2 = open(file_path_write_buffer_2, mode="wb", buffering=3)
# 超过3个字节的输入,都会直接写入到物理文件中
file_write_buffer_2.write("我靠".encode("UTF-8"))
file_write_buffer_2.write("8888".encode("UTF-8"))
file_write_buffer_2.write("111\n".encode("UTF-8"))
file_write_buffer_2.flush()
file_write_buffer_2.close()
简单应用实践
复制文本文件
# 文本文件复制
file_source = open("./copy_source.csv", "r", encoding="utf-8")
file_target = open("./copy_target.csv", "w", encoding="utf-8")
file_target.write("name,age,score,type\n")
for line in file_source:
# 去掉两端的空格,最主要的是去掉最后的换行符
line = line.strip()
line_parts = line.split(",")
if len(line_parts) < 4 or (not str(line_parts[2]).isdigit()):
continue
if int(line_parts[2]) >= 100 and line_parts[3] == 'prod':
file_target.write(line + "\n")
file_source.close()
file_target.close()
复制二进制文件 比如视频
# 二进制复制,比如视频
# 这里就不把视频上传到GitHub了,太大了
file_binary_source = open("F:/羽毛球打球视频/2022年09月30日/VID_20220930_184501.mp4", "rb")
file_binary_target = open("F:/羽毛球打球视频/2022年09月30日/VID_20220930_184501_复制.mp4", "wb", )
while True:
# 一次读取2kb
content_binary = file_binary_source.read(2048)
# 空字节 b'' ,作为条件表达式,会被bool()转化为 Boolean,结果为 False
if content_binary:
file_binary_target.write(content_binary)
else:
break
file_binary_source.close()
file_binary_target.close()